<?
/**********************************************************************
 *                                                                    *    
 * Copyright (c) 2009 Dmytro Bezhnar. All rights reserved.                  *
 *                                                                    *
 **********************************************************************/

/**
 * Ageset entity manager.
 *
 * @version $Id: TreeManager.php,v 1.4 2008/10/02 07:33:39 sdobrovol Exp $
 */

class TreeManager extends ORMManager {
	
	public $name;
	
	public $unsetNodes_arr = array();
	
	public $root_area_name = 'root';

	public $path_url = '';
	
	public $table_fields = array(
		'id'        => 'id',
		'tree_name' => 'name',
		'parent_id' => 'parent_id',
		'prio'      => 'prio'
	);
	
	public $table_name = null;

	function __construct($dialog, $jsObjectName = 'd', $table_name = 'tree')
	{
		parent::__construct();
		$this->dialog     = $dialog;
		$this->name       = $jsObjectName;
		$this->table_name = $table_name;
		$this->path_url   = '?target='.$dialog->target.'&event='.$dialog->event;
		$this->set_names();
	}

	
	
	
/**#@+
  * Set-��� � Get-���
  */
	
	/**
	 * ������������� ��� ������� ��� JavaScript
	 *
	 * @param string $jsObjectName
	 */
	function set_names() {
		$this->id_name            = $this->name.'_id';
		$this->set_root_tree_name = $this->name.'_set_root_tree';
	}
	
/**#@-*/	
	
	
	
	
	
/**#@+
  * ��������� ������
  */
	
	
	/**
	 * �������� ������ �� ����
	 *
	 */
	protected function _loadTree() {
		$dialog = $this->dialog;
		$fields  = &$this->table_fields;
		$arr = array();
		
		foreach ($fields as $fieldID => &$field) {
			array_push($arr, $field.' as '.$fieldID);
		}

		$qs = "select ".join(', ',$arr)." from ".$this->table_name;
		
		#print $qs;

		$this->tree = $this->getArray($qs);
	}
	
	/**
	 * ������� ���������� ������
	 *
	 */
	private function _indexTree() {
		# index tree
		$this->tree_idx = array();
		foreach ($this->tree as &$item) {
			$this->tree_idx[$item['id']] = $item;
		}
	}
	
	/**
	 * ����� ���������� ������ ��� ����������
	 *
	 */
	function _sortTree() {
		# index tree
		$this->tree_sort = array();
		foreach ($this->tree_idx as $id => &$item) {
			if (!is_array($this->tree_sort[$item['parent_id']])) {
				$this->tree_sort[$item['parent_id']] = array();
			}
			array_push($this->tree_sort[$item['parent_id']], $id);
		}
	}
	
	/**
	 * ���������� ������ ��� �������� ������ � �������
	 *
	 */
	function _sortTreeRoutine($id) {
		if (!is_array($this->tree_sort_lines)) {
			$this->tree_sort_lines = array();
		}
		if (count($this->tree_sort)) {
			foreach ($this->tree_sort[$id] as $item) {
				array_push($this->tree_sort_lines,&$this->tree_idx[$item]);
				if (is_array($this->tree_sort[$item])) {
					$this->_sortTreeRoutine($item);
				} 
			}
		}
	}
	

	/**
	 * ��������� ������� ��� �����������
	 *
	 */
	private function _setCookiesTree() {
		$dialog = $this->dialog;
		$id_name = $this->id_name;
		$set_root_tree_name = $this->set_root_tree_name;
		
		# index tree
		if (! ($dialog->$id_name) and ! ($dialog->$set_root_tree_name)) {
			$dialog->$id_name = $_COOKIE['cs'.$this->name];
		}
		$this->id = $dialog->$id_name;
		$this->set_root_tree = $dialog->$set_root_tree_name;
		$this->tree_name = $this->tree_idx[$this->id]['tree_name'];
	}
	

	/**
	 * ��������� ����
	 *
	 */
	private function _makePath() {
		$this->tree_path = array();
		$id = $this->id;
		
		while ($id) {
			array_unshift($this->tree_path,
				array(name => $this->tree_idx[$id]['tree_name'], 
				      url  => $this->path_url.'&'.$this->id_name.'='.$id
				)
			);
			$id = $this->tree_idx[$id]['parent_id'];
		}
		array_unshift($this->tree_path,
			array(
				name => $this->root_area_name, 
				url  => $this->path_url.'&'.$this->set_root_tree_name.'=1'
			)
		);
		unset($this->tree_path[count($this->tree_path)-1]['url']);
		
	}

	/**
	 * ��������� ���� �� � ����� ���������� �������� ������� � check_id
	 *
	 */
	private function _checkPath($id, $check_id) {
		if (! is_array($this->tree_idx)) {
			$this->_loadTree();
			$this->_indexTree();
		}
		while ($check_id) {
			if ($check_id == $id) {
				return true;
			}
			$check_id = $this->tree_idx[$check_id]['parent_id'];
		}
		return false;
	}


	/**
	 * ��������� �������� level � ������. 
	 * �������� ������ � ��������������� ���������!
	 */
	protected function _make_levels() {
		reset($this->tree_sort_lines);
		foreach ($this->tree_sort_lines as &$item) {
			$item['level'] = $this->tree_idx[$item['parent_id']]['level']+1;
		}
	}
	
	
/**#@-*/	


/**#@+
  * ��������� ������
  */

	
	/**
	 * ���������� ����������� ������ ��� ����������� �������� �������.
	 * �������������� �������� ���������������� �� �������
	 *
	 */
	function prepareClientTree() {
		$this->_indexTree();
		$this->_setCookiesTree();
		$this->_makePath();
	}
	
	/**
	 * �������� ������ ��� ����������� �������� �������.
	 * �������������� �������� ���������������� �� �������
	 *
	 */
	function makeClientTree() {
		$this->_loadTree();
		$this->prepareClientTree();
	}

	/**
	 * �������� ������ ��� ����������� �������� �������.
	 * �������������� �������� ���������������� �� �������
	 *
	 */
	function makeSortedClientTree() {
		if (! is_array($this->tree)) {
			$this->makeClientTree();
		}
		if (! is_array($this->tree_sort)) {
			$this->_sortTree();
		}
		if (count($this->unsetNodes_arr))
		{
			$this->unsetNodes($this->unsetNodes_arr);
		}
		$this->_sortTreeRoutine(0);
		
	}

	
	function unsetNodes($unset_arr)
	{
		foreach ($unset_arr as $item)
		{
			if (isset($this->tree_sort[$item]))
			{
				$this->unsetNodes($this->tree_sort[$item]);
			
				foreach ($this->tree_sort[$this->tree_idx[$item]['parent_id']] as $key=>$item_parent)
				{
					if ($item_parent == $item)
					{
						unset($this->tree_sort[$this->tree_idx[$item]['parent_id']][$key]);
					}
				}
				unset($this->tree_sort[$item]);
			}
		}
	}
	
	/**
	 * ��������� ������� ��������� (levels) � ������
	 *
	 */
	function make_levels($delimiter=' ') {
		if (! is_array($this->tree_sort_lines)) {
			$this->makeSortedClientTree();
		}
		$this->_make_levels();
	}

	
	/**
	 * ���������� ������ ��� smarty html_options
	 *
	 */
	function make_html_options($delimiter=' ') {
		$result = array();
		$this->make_levels();
		foreach ($this->tree_sort_lines as &$item) {
			#print "parent_id = ".$item['parent_id']." id=".$item['id']." level=".$item['level']."\n";
			$result[$item['id']] = str_repeat($delimiter,($item['level']-1)).$item['tree_name'];
		}
		return $result;
	}
	
	
	
	/**
	 * ��������� ID-��� ��� ������� ����� ������
	 * 0 - ��� ����� ������
	 *
	 */
	function getTreeIDsFromID(&$stack,$id=0) {
		if (is_array($this->tree_sort[$id])) {
			foreach ($this->tree_sort[$id] as $item) {
				$stack[$item] = &$this->tree_idx[$item];
				if (is_array($this->tree_sort[$item])) {
					$this->getTreeIDsFromID($stack,$item);
				} 
			}
		} else {
			$stack[$id] = &$this->tree_idx[$id];
		}
	}
	
	
	/**
	 * 
	 */
	protected function _get_parent_by_id_sql($id) {
		$fields  = &$this->table_fields;
		
	    $qs = "select parent_id as count from ".$this->table_name." where ".$fields['id']." = $id";
		#print $qs;
		return $this->getCount($qs);
	}
	
	/**
	 * ��������� ���� �� � ���������� � �������� ��������
	 * � SQL-����
	 * 
	 */
	private function _is_found_parents_sql($id) {
		$dialog  = $this->dialog;
		$fields  = &$this->table_fields;
		
	    $qs = "select count(*) as count from ".$this->table_name." where ".$fields['parent_id']." = $id";
		
		return $this->getCount($qs);
	}

	/**
	 * ��������� ���� �� � ���������� � �������� ��������
	 * � ��� ���������� ������
	 * 
	 */
	function is_found_parents($id=0) {
		if ($id  == 0) {
			$id_name = $this->id_name;
			$id = $this->dialog->$id_name + 0;
		}
		if (! count($this->tree_idx)) {
			return $this->_is_found_parents_sql($id);
		}
		foreach ($this->tree_idx as &$item) {
			if ($item['parent_id'] == $id) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 
	 */
	function get_name_by_id($id) {
	    if (!$this->tree_idx){
            $this->_loadTree();
            $this->_indexTree();
	    }
		return $this->tree_idx[$id]['tree_name'];
	}
	
	/**
	 * ��������� ������� � ������
	 *
	 */
	function addTreeItem () {
		$dialog = $this->dialog;
		$id_name = $this->id_name;
		$id = $dialog->$id_name + 0;
		$fields = &$this->table_fields;
		$class_name=ucfirst($this->table_name).'DB';
		$tree = new $class_name;
		$tree->$fields['tree_name']=$dialog->tree_name;
		$tree->$fields['parent_id']=$id;
		$this->insert($tree);
		/*$qs="INSERT into ".$this->table_name."
				set ".$fields['tree_name']." = '".$dialog->tree_name."',
					".$fields['parent_id']." = $id";
		$dialog->execQuery($qs);*/
		$dialog->returnUrl=$this->path_url.'&'.$this->id_name.'='.$id;
		return $tree->$fields['id'];
	}

	/**
	 * ��������������� ������� ������
	 *
	 */
	function renameTreeItem () {
		$dialog = $this->dialog;
		$id_name = $this->id_name;
		$id = $dialog->$id_name + 0;
		$fields = &$this->table_fields;
		
		$qs="update ".$this->table_name."
			    set ".$fields['tree_name']." = '".$dialog->tree_name."'
			  where ".$fields['id']." = $id";
		$this->execQuery($qs);
		$dialog->returnUrl=$this->path_url.'&'.$this->id_name.'='.$id;
	}
	
	/**
	 * ������� ������� �� ������
	 *
	 */
	function deleteTreeItem () {
		$dialog = $this->dialog;
		$id_name = $this->id_name;
		$id = $dialog->$id_name + 0;
		$fields = &$this->table_fields;
		
		if (! $this->is_found_parents($id)) {

			$qs="delete from ".$this->table_name."
			      where ".$fields['id']." = $id";
			if (isset($this->tree_idx[$id])) {
				$this->id = $this->tree_idx[$id]['parent_id'];
			} else {
				$this->id = $this->_get_parent_by_id_sql($id);
			}
			$this->execQuery($qs);
			
			if ($this->id == 0)  {
				$add = '&'.$this->set_root_tree_name.'=1';
			}
		} else {
			$dialog->valid = false;
			$dialog->found_parents = true;
		}
		
		$dialog->returnUrl=$this->path_url.'&'.$this->id_name.'='.$this->id.$add;
	}
	
	/**
	 * ���������� ������� � ������
	 *
	 */
	function moveTreeItem () {
		$dialog = $this->dialog;
		$id_name = $this->id_name;
		$id = $dialog->$id_name + 0;
		$dialog->tree_id += 0;
		$fields = &$this->table_fields;

		if ($this->_checkPath($id,$dialog->tree_id)) {
			$dialog->valid = false;
			$dialog->tree_move_error = true;
		} else {
			$qs="update ".$this->table_name."
				    set ".$fields['parent_id']." = '".$dialog->tree_id."'
				  where ".$fields['id']." = $id";
			$this->execQuery($qs);
		}
		
		$dialog->returnUrl=$this->path_url.'&'.$this->id_name.'='.$id;
	}
	
/**#@-*/

	
}
?>